package com.smart.community.region.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.smart.community.commons.annotation.ApiLog;
import com.smart.community.commons.enums.ApiLogOperationType;
import com.smart.community.commons.result.PageResult;
import com.smart.community.commons.result.Result;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.region.dto.UnitDTO;
import com.smart.community.region.dto.UnitQueryDTO;
import com.smart.community.region.entity.Unit;
import com.smart.community.region.service.IUnitService;
import com.smart.community.region.vo.UnitVO;
import com.smart.community.region.vo.UnitDeleteImpactVO;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import cn.dev33.satoken.annotation.SaCheckPermission;

/**
 * 单元管理控制器
 * 
 * @author Wu.Liang
 * @version 1.0.0
 * @since 2025-01-30
 */
@Slf4j
@RestController
@RequestMapping("/region/units")
@Tag(name = "单元管理", description = "单元管理相关接口")
public class UnitController {

    @Autowired
    private IUnitService unitService;

    // ==================== 基础CRUD接口 ====================

    /**
     * 分页查询单元列表
     * 
     * @param queryDTO 查询条件
     * @return 单元分页列表
     * @throws Exception 统一异常
     */
    @GetMapping
    @Operation(summary = "分页查询单元列表", description = "根据条件分页查询单元列表")
    public Result<PageResult<UnitVO>> getUnitPage(@Parameter(description = "查询条件") UnitQueryDTO queryDTO) throws Exception {
        log.info("分页查询单元列表，查询条件：{}", queryDTO);
        PageResult<UnitVO> result = unitService.getUnitPage(queryDTO);
        return Result.success(result);
    }

    /**
     * 获取单元详情
     * 
     * @param unitId 单元ID
     * @return 单元详情
     * @throws Exception 统一异常
     */
    @GetMapping("/{unitId}")
    @Operation(summary = "获取单元详情", description = "根据单元ID获取单元详细信息")
    public Result<UnitVO> getUnitDetail(@Parameter(description = "单元ID") @PathVariable Long unitId) throws Exception {
        log.info("获取单元详情，单元ID：{}", unitId);
        UnitVO unit = unitService.getUnitById(unitId);
        if (unit == null) {
            return Result.error("单元不存在");
        }
        return Result.success(unit);
    }

    /**
     * 创建单元
     * 
     * @param unitDTO 单元信息
     * @return 创建结果
     * @throws Exception 统一异常
     */
    @ApiLog(logTitle = "创建单元", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.ADD)
    @PostMapping
    @Operation(summary = "创建单元", description = "创建新的单元")
    public Result<UnitVO> createUnit(@Parameter(description = "单元信息") @RequestBody @Valid UnitDTO unitDTO) throws Exception {
        log.info("创建单元，单元信息：{}", unitDTO);
        Result<UnitVO> result = unitService.addUnit(unitDTO);
        return result;
    }

    /**
     * 更新单元
     * 
     * @param unitId 单元ID
     * @param unitDTO 单元信息
     * @return 更新结果
     * @throws Exception 统一异常
     */
    @ApiLog(logTitle = "更新单元", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.UPDATE)
    @PutMapping("/{unitId}")
    @Operation(summary = "更新单元", description = "更新单元信息")
    public Result<UnitVO> updateUnit(@Parameter(description = "单元ID") @PathVariable Long unitId,
            @Parameter(description = "单元信息") @RequestBody @Valid UnitDTO unitDTO) throws Exception {
        log.info("更新单元，单元ID：{}，单元信息：{}", unitId, unitDTO);
        unitDTO.setId(unitId);
        Result<UnitVO> result = unitService.updateUnit(unitDTO);
        return result;
    }

    /**
     * 删除单元（带关联检查）
     * 
     * @param unitId 单元ID
     * @return 删除结果
     * @throws Exception 统一异常
     */
    @DeleteMapping("/{unitId}")
    @Operation(summary = "删除单元", description = "删除指定单元，会检查并处理所有关联数据")
    @SaCheckPermission("region:unit:delete")
    @ApiLog(logTitle = "删除单元", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
    public Result<String> deleteUnit(@Parameter(description = "单元ID") @PathVariable Long unitId) throws Exception {
        log.info("删除单元，单元ID：{}", unitId);
        Long currentUserId = SecurityUtils.getCurrentUserId();
        String result = unitService.deleteUnitWithRelations(unitId, currentUserId);
        return Result.success(result);
    }

    /**
     * 批量删除单元（带关联检查）
     * 
     * @param unitIds 单元ID列表
     * @return 删除结果
     * @throws Exception 统一异常
     */
    @DeleteMapping("/batch")
    @Operation(summary = "批量删除单元", description = "批量删除单元，会检查并处理所有关联数据")
    @SaCheckPermission("region:unit:delete")
    @ApiLog(logTitle = "批量删除单元", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
    public Result<String> batchDeleteUnits(@Parameter(description = "单元ID列表") @RequestBody List<Long> unitIds) throws Exception {
        log.info("批量删除单元，单元ID列表：{}", unitIds);
        Long currentUserId = SecurityUtils.getCurrentUserId();
        String result = unitService.batchDeleteUnitsWithRelations(unitIds, currentUserId);
        return Result.success(result);
    }

    // ==================== 查询接口 ====================

    /**
     * 根据单元编码获取单元
     * 
     * @param unitCode 单元编码
     * @return 单元信息
     * @throws Exception 统一异常
     */
    @GetMapping("/code/{unitCode}")
    @Operation(summary = "根据单元编码获取单元", description = "根据单元编码获取单元信息")
    public Result<UnitVO> getUnitByCode(@Parameter(description = "单元编码") @PathVariable String unitCode) throws Exception {
        log.info("根据单元编码获取单元，单元编码：{}", unitCode);
        UnitVO unit = unitService.getUnitByCode(unitCode);
        if (unit == null) {
            return Result.error("单元不存在");
        }
        return Result.success(unit);
    }

    /**
     * 根据楼栋ID获取单元列表
     * 
     * @param buildingId 楼栋ID
     * @return 单元列表
     * @throws Exception 统一异常
     */
    @GetMapping("/building/{buildingId}")
    @Operation(summary = "根据楼栋ID获取单元列表", description = "获取指定楼栋下的所有单元")
    @SaCheckPermission("region:unit:view")
    @ApiLog(logTitle = "获取单元列表", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.QUERY)
    public Result<List<UnitVO>> getUnitListByBuilding(@Parameter(description = "楼栋ID") @PathVariable Long buildingId) throws Exception {
        log.info("根据楼栋ID获取单元列表，楼栋ID：{}", buildingId);
        List<UnitVO> units = unitService.getUnitListByBuilding(buildingId);
        return Result.success(units);
    }

    /**
     * 根据社区ID批量查询单元，支持按楼栋分组返回
     * 
     * @param communityIds 社区ID列表，逗号分隔
     * @param buildingIds 楼栋ID列表，逗号分隔
     * @param groupByBuilding 是否按楼栋分组
     * @return 单元列表或分组结果
     * @throws Exception 统一异常
     */
    @GetMapping("/queryByCommunity")
    @Operation(summary = "根据社区ID批量查询单元，支持按楼栋分组返回")
    public Result<?> queryUnitsByCommunity(@Parameter(description = "社区ID列表，逗号分隔") @RequestParam String communityIds,
            @Parameter(description = "楼栋ID列表，逗号分隔") @RequestParam(required = false) String buildingIds,
            @Parameter(description = "是否按楼栋分组") @RequestParam(required = false, defaultValue = "false") Boolean groupByBuilding) throws Exception {
        log.info("根据社区ID批量查询单元，社区ID列表：{}，楼栋ID列表：{}，是否分组：{}", communityIds, buildingIds, groupByBuilding);
        
        if (!StringUtils.hasText(communityIds)) {
            return Result.error("参数communityIds不能为空");
        }

        List<Long> communityIdList = new ArrayList<>();
        for (String id : communityIds.split(",")) {
            if (StringUtils.hasText(id)) {
                communityIdList.add(Long.valueOf(id.trim()));
            }
        }

        if (communityIdList.isEmpty()) {
            return Result.error("有效的社区ID不能为空");
        }

        List<Long> buildingIdList = null;
        if (StringUtils.hasText(buildingIds)) {
            buildingIdList = new ArrayList<>();
            for (String id : buildingIds.split(",")) {
                if (StringUtils.hasText(id)) {
                    buildingIdList.add(Long.valueOf(id.trim()));
                }
            }
        }

        if (Boolean.TRUE.equals(groupByBuilding)) {
            Map<Long, List<Unit>> groupedUnits = unitService.getUnitsGroupedByBuilding(communityIdList, buildingIdList);
            return Result.success(groupedUnits);
        } else {
            List<Unit> unitList = unitService.getUnitsByCommunityIds(communityIdList, buildingIdList);
            return Result.success(unitList);
        }
    }

    /**
     * 获取单元下的房户列表
     * 
     * @param unitId 单元ID
     * @return 房户列表
     * @throws Exception 统一异常
     */
    @GetMapping("/{unitId}/households")
    @Operation(summary = "获取单元下的房户列表", description = "获取指定单元下的所有房户")
    public Result<List<Object>> getHouseholdsByUnit(@Parameter(description = "单元ID") @PathVariable Long unitId) throws Exception {
        log.info("获取单元下的房户列表，单元ID：{}", unitId);
        List<Object> result = unitService.getHouseholdsByUnit(unitId);
        return Result.success(result);
    }

    // ==================== 状态管理接口 ====================

    /**
     * 更新单元状态
     * 
     * @param unitId 单元ID
     * @param status 状态：0-禁用，1-启用
     * @return 更新结果
     * @throws Exception 统一异常
     */
    @ApiLog(logTitle = "更新单元状态", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.UPDATE)
    @PutMapping("/{unitId}/status")
    @Operation(summary = "更新单元状态", description = "更新单元状态")
    public Result<Boolean> updateUnitStatus(@Parameter(description = "单元ID") @PathVariable Long unitId,
            @Parameter(description = "状态：0-禁用，1-启用") @RequestParam Integer status) throws Exception {
        log.info("更新单元状态，单元ID：{}，状态：{}", unitId, status);
        boolean result = unitService.updateUnitStatus(unitId, status);
        return Result.success(result);
    }

    /**
     * 批量更新单元状态
     * 
     * @param unitIds 单元ID列表
     * @param status 状态：0-禁用，1-启用
     * @return 更新结果
     * @throws Exception 统一异常
     */
    @ApiLog(logTitle = "批量更新单元状态", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.UPDATE)
    @PutMapping("/batch/status")
    @Operation(summary = "批量更新单元状态", description = "批量更新多个单元的状态")
    public Result<Boolean> batchUpdateUnitStatus(@Parameter(description = "单元ID列表") @RequestBody List<Long> unitIds,
            @Parameter(description = "状态：0-禁用，1-启用") @RequestParam Integer status) throws Exception {
        log.info("批量更新单元状态，单元ID列表：{}，状态：{}", unitIds, status);
        boolean result = unitService.batchUpdateUnitStatus(unitIds, status);
        return Result.success(result);
    }

    // ==================== 验证接口 ====================

    /**
     * 检查单元编码唯一性
     * 
     * @param unitCode 单元编码
     * @param excludeUnitId 排除的单元ID
     * @return 是否唯一
     * @throws Exception 统一异常
     */
    @GetMapping("/check/code")
    @Operation(summary = "检查单元编码唯一性", description = "检查单元编码是否已存在")
    public Result<Boolean> checkUnitCodeUnique(@Parameter(description = "单元编码") @RequestParam String unitCode,
            @Parameter(description = "排除的单元ID") @RequestParam(required = false) Long excludeUnitId) throws Exception {
        log.info("检查单元编码唯一性，单元编码：{}，排除单元ID：{}", unitCode, excludeUnitId);
        boolean result = unitService.checkUnitCodeUnique(unitCode, excludeUnitId);
        return Result.success(result);
    }

    // ==================== 删除影响检查接口 ====================

    /**
     * 检查单元删除影响
     * 
     * @param unitId 单元ID
     * @return 删除影响分析
     * @throws Exception 统一异常
     */
    @GetMapping("/{unitId}/delete-impact")
    @Operation(summary = "检查单元删除影响", description = "分析删除单元会对哪些关联数据造成影响")
    @SaCheckPermission("region:unit:view")
    @ApiLog(logTitle = "检查单元删除影响", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.QUERY)
    public Result<UnitDeleteImpactVO> checkDeleteImpact(@Parameter(description = "单元ID") @PathVariable Long unitId) throws Exception {
        log.info("检查单元删除影响，单元ID：{}", unitId);
        UnitDeleteImpactVO impact = unitService.checkDeleteImpact(unitId);
        return Result.success(impact);
    }

    // ==================== 统计接口 ====================

    /**
     * 获取单元统计信息
     * 
     * @param unitId 单元ID
     * @return 统计信息
     * @throws Exception 统一异常
     */
    @GetMapping("/{unitId}/stats")
    @Operation(summary = "获取单元统计信息", description = "获取指定单元的统计信息")
    public Result<Object> getUnitStats(@Parameter(description = "单元ID") @PathVariable Long unitId) throws Exception {
        log.info("获取单元统计信息，单元ID：{}", unitId);
        Object result = unitService.getUnitStats(unitId);
        return Result.success(result);
    }

    // ==================== 缓存管理接口 ====================

    /**
     * 清除单元缓存
     * 
     * @param unitId 单元ID
     * @return 清除结果
     * @throws Exception 统一异常
     */
    @ApiLog(logTitle = "清除单元缓存", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
    @DeleteMapping("/cache/{unitId}")
    @Operation(summary = "清除单元缓存", description = "清除指定单元的缓存")
    public Result<Boolean> clearUnitCache(@Parameter(description = "单元ID") @PathVariable Long unitId) throws Exception {
        log.info("清除单元缓存，单元ID：{}", unitId);
        unitService.clearUnitCache(unitId);
        return Result.success(true);
    }

    /**
     * 清除所有单元缓存
     * 
     * @return 清除结果
     * @throws Exception 统一异常
     */
    @ApiLog(logTitle = "清除所有单元缓存", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
    @DeleteMapping("/cache/all")
    @Operation(summary = "清除所有单元缓存", description = "清除所有单元相关的缓存")
    public Result<Boolean> clearAllUnitCache() throws Exception {
        log.info("清除所有单元缓存");
        unitService.clearAllUnitCache();
        return Result.success(true);
    }
}